namespace hasTools {
    // 所有的内置类型几乎可以自己写
    interface Todo {
        title: string;
        description: string;
        name: string;
    }


    // 可选类型
    type zz = Partial<Todo>;
    type MyPar<T> = {
        [P in keyof T]+?: T[P];
    }
    type zzz = MyPar<Todo>

    // pick 从属性中挑选一个
    type zs = Pick<Todo, "description">;

    type Mypick<T, U extends keyof T> = {
        [sessadas in U]: T[sessadas];
    };

    //   创建一个新类型
    type re = Record<"zzz", number>;
    //   创建一个新类型

    // type Record<K extends keyof any, T> = {
    //     [P in K]: T;
    // };
    type res = Record<"ada" | "sdf" | 1456, number | string>;

    let data2: res = {
        "1456": 0, ada: 0, sdf: 0

    }

    type MyMap<P extends keyof any> = {
        [T in P]: string;
    };
    type Keys = "name" | "age" | 1232;
    type Result = MyMap<Keys>;


    type zkssl = "zzks" | "skda" | "zmv"

    type MapS<K extends zkssl, T> = {
        [P in K]: T
    }

    type    usemap = MapS<"skda", number>
    let dat2: usemap = {
        "skda": 123
    }

    type MyMap2<P extends string | number | symbol> = {
        [T in keyof P]: string;
    };
    type Keys2 = "name" | "age";
    type Result2 = MyMap2<Keys2>;


    // omit 类型

    // type myOmit<T, K exteOmnds keyof T> = {
    //   [P in Exclude<keyof T, K>]: T[P];
    // };
    type myOmit<T, K extends keyof T> = {
        [P in keyof T as Exclude<P, K>]: T[P];
    };
    type fdd = myOmit<Todo, "name">;

    interface St {
        name: string
        age: number
        add: string
    }

    // type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;


    class Pp {
        static uname: string
        age: number

        constructor(age: number, uname: string) {
            this.age = age
        }

        static getName() {
            return Pp.uname
        }

        getAge() {
            return this.age
        }

    }

// 根据构造函数类型创建数组和元祖
    type sdsad = ConstructorParameters<typeof Pp>
    let asdsad: sdsad = [1, '1']


    declare function zks(a: string, b: number, c: boolean): string


    type zks = Parameters<typeof zks>
    let sadasd: zks = ['1', 1, false]

    // NoInfer 是一种技巧，用来阻止 TypeScript 推导泛型参数。
    // 这通常是用来强制某个参数必须从前面的参数推导出类型后再验证，而不能自己影响推导过程。
    function createStreetLight<C extends string>(
        colors: C[],
        defaultColor?: NoInfer<C>,
    ) {
        // ...
    }

    createStreetLight(["red", "yellow", "green"], "red");  // OK
    createStreetLight(["red", "yellow", "green"], "blue");  // Error


// NoInfer 是什么？
// NoInfer 是一种技巧，用来阻止 TypeScript 推导泛型参数。这通常是用来强制某个参数必须从前面的参数推导出类型后再验证，而不能自己影响推导过程。
// 常见写法如下：
//     type NoInfer<T> = [T][T extends any ? 0 : never];
//     这个类型包装方式让 TypeScript 不会从这个位置去推断类型 T，而是只能接受已经确定的 T。
// 解释这两个调用：
// ✅ OK：
//     createStreetLight(["red", "yellow", "green"], "red");
//     colors 是 ["red", "yellow", "green"]
//     TypeScript 推导出 C = "red" | "yellow" | "green"
//     defaultColor 是 "red"，满足 "red" extends C
// ✅ 所以通过。
//     createStreetLight(["red", "yellow", "green"], "blue");
//     colors 推导出 C = "red" | "yellow" | "green"
////     defaultColor 是 "blue"，它 不属于 C 的联合类型
//     由于 NoInfer<C> 强制类型校验而不是重新推导，"blue" 被严格验证是否在 "red" | "yellow" | "green" 中
/// ❌ "blue" 不符合，所以报错
}


// ⛳️ 所以 T 怎么“复制”的？
// 其实：
// T 是一个自由的占位符
// 它不会被“赋值”，而是被用作函数泛型推导的一部分
// TypeScript 会尝试“在所有 T 情况下”比较两个函数返回值是否一致
// 这是 TS 类型系统的函数兼容性检测机制自动完成的

// 这不是传参用的 T，而是一个“万能测试器”，让 TypeScript 用它试遍所有可能的类型 T，看看：
// T extends A 和 T extends B 这两种测试规则
//
// 在所有情况下是否完全一致
// 如果一致 → A == B，返回 true，否则 false
// 说白了就是硬凑所有的可能性，是不是都出现相等的情况
type Equal<A, B> =
    (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2)
        ? true
        : false;

type E1 = Equal<"x", "x">  // true ✅
type E2 = Equal<"x", string>  // false ❌

//
// TypeScript 并不会真的枚举出所有可能的 T 值，因为类型是无限的，但它会隐式地认为 T 是“任意类型”，也就是：
// 对于任意 T，T extends A 和 T extends B 的结果是否总是一样？
// 所以我们不能穷举出 全部 T，但我们可以列出典型的、常见参与比较的类型，这些类型能代表判断行为的差异性。

// 所以我们可以列出这些代表性类型来说明 T 的“测试集合”：
// 类型类别	示例	说明
// 字面量类型	"x"、1、true、false	常用基础类型的具体值
// 原始类型	string、number、boolean、symbol	宽泛基本类型
// 特殊类型	null、undefined、any、unknown、never	类型系统中的关键值
// 对象类型	{}、{ name: string }、[]	普通对象与数组结构
// 函数类型	() => void、(a: number) => string	类型系统支持的函数结构
// 联合类型	`"x"	"y"、number
// 交叉类型	{ name: string } & { age: number }	对象合并结构
// 泛型类型	T[]、Record<string, T>	泛化结构测试
// 元组类型	[number, string]、[]	特殊的数组形式
// 类、实例	Date、RegExp、Error	一些内建对象类型
// 构造器 / symbol	typeof Symbol、typeof Date	复杂类型行为测试

//     | T           | T extends "x" | T extends string | 一致？ |
// | ----------- | ------------- | ---------------- | --- |
// | `"x"`       | ✅ true        | ✅ true           | ✅   |
// | `"y"`       | ❌ false       | ✅ true           | ❌   |
// | `string`    | ❌ false       | ✅ true           | ❌   |
// | `number`    | ❌ false       | ❌ false          | ✅   |
// | `null`      | ❌ false       | ❌ false          | ✅   |
// | `undefined` | ❌ false       | ❌ false          | ✅   |
// | `any`       | ✅ true        | ✅ true           | ✅   |
// | `never`     | ✅ true        | ✅ true           | ✅   |
// | `unknown`   | ❌ false       | ❌ false          | ✅   |

// 因为我们发现 "y"、string 会出现判断差异，所以 Equal<"x", string> 为 false。